package gui.components;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.border.TitledBorder;

import controller.Constants;
import controller.UserListController;
import data.WorkingMode;
import data.WorkingMode.MODE;

/**
 * Client list panel is a gui component which is used to list users who are
 * currently connected to the server and allow server host to kick client users.
 * 
 * @author Jie Zhao(288654)
 * 
 */
public class ClientListPanel extends JPanel implements MouseListener, Observer {
	private JPanel userListPanel = new JPanel();
	private JScrollPane userListScrollPanel = new JScrollPane();
	private JList userList = new JList();
	private UserListController controller = UserListController.getInstance();
	JButton kickButton = new JButton("Kick");
	Popup kick = null;

	public ClientListPanel() {
		WorkingMode.getInstance().addObserver(this);
		this.setLayout(new BorderLayout());
		userListPanel.setLayout(new BorderLayout());
		userListPanel.setPreferredSize(new Dimension(120, 600));
		userListPanel.setBorder(new TitledBorder(null, "User List:",
				TitledBorder.DEFAULT_JUSTIFICATION,
				TitledBorder.DEFAULT_POSITION, null, null));

		userListPanel.add(userListScrollPanel);
		userListScrollPanel.setPreferredSize(new Dimension(150, 400));

		userList.addMouseListener(this);
		userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		// fakeuser();
		userListScrollPanel.setViewportView(userList);
		this.add(userListPanel);

		kickButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				kickUser((String) userList.getSelectedValue());
				kick.hide();
			}
		});
		// fakeData();
	}

	// public void addUser(String username) {
	// users.add(username);
	// update();
	// }
/**
 * Kick a user
 */
	public void kickUser(String username) {
		if (username != null)
			controller.kickUser(username);
	}

	/**
	 * update the list by the given user list
	 * @param users
	 */
	public void update(List<String> users) {
		if (Constants.DEBUG)
			System.out.println("Client List changed, updating data...");
		userList.setListData(users.toArray());
	}

	/**
	 * disable control of the list
	 */
	public void disable() {
		userList.setEnabled(false);
		kickButton.setEnabled(false);
	}

	/**
	 * enable control of the list
	 */
	public void enable() {
		userList.setEnabled(true);
		kickButton.setEnabled(true);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON3 && userList.isEnabled()) {
			Point cursorLocation = e.getPoint();
			if (userList.contains(cursorLocation)) {
				userList.setSelectedIndex(userList
						.locationToIndex(cursorLocation));
			}

			if (!userList.isSelectionEmpty()) {
				if (kick != null) {
					kick.hide();
					kick = null;
				}
				kick = PopupFactory.getSharedInstance().getPopup(null,
						kickButton, e.getXOnScreen(), e.getYOnScreen());
				kick.show();
			}
		} else if (e.getButton() == MouseEvent.BUTTON1) {
			if (kick != null) {
				kick.hide();
				kick = null;
			}

		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	// private void fakeData() {
	// for (int i = 0; i < 50; i++) {
	// addUser("User" + i);
	// }
	// }

	@Override
	public void update(Observable o, Object arg) {
		WorkingMode wm = WorkingMode.getInstance();
		if (wm.getWorkingMode() == MODE.SERVER
				|| wm.getWorkingMode() == MODE.LOCAL) {
			enable();
		} else if (wm.getWorkingMode() == MODE.CLIENT) {
			disable();
		}
		if (wm.getWorkingMode() == MODE.LOCAL) {
			controller.clear();
		}
	}
}
